package com.tianluo.tianluobookstore.service.impl;

import com.github.pagehelper.PageInfo;
import com.tianluo.tianluobookstore.BookPO;
import com.tianluo.tianluobookstore.domain.view.BookPageVO;
import com.tianluo.tianluobookstore.domain.view.BookVO;
import com.tianluo.tianluobookstore.enums.CommonCodeEnum;
import com.tianluo.tianluobookstore.exception.BizException;
import com.tianluo.tianluobookstore.repository.BookRepository;
import com.tianluo.tianluobookstore.request.AddBookRequest;
import com.tianluo.tianluobookstore.request.QueryBookRequest;
import com.tianluo.tianluobookstore.service.BookService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class BookServiceImpl implements BookService {

    @Autowired
    private BookRepository bookRepository;

    @Autowired
    private CacheManager cacheManager;

    private final Long DELAY_DELETE_TIME = 5000L;

    private static final String BASE_PATH = "http://localhost:8081";

    @Override
    public int addBook(AddBookRequest request) {

        //查询book实体
        BookPO bookPO = bookRepository.queryByIsbn(request.getIsbn());
        //如果为空，则插入，否则直接更新数量
        if (Objects.isNull(bookPO)) {
            //处理书本图片
            String fileImageUrl = uploadBookImage(request.getCoverImage());
            BookPO newBookPO = buildBookPO(request, fileImageUrl);
            try {
                return bookRepository.insertBook(newBookPO);
            } catch (Exception e) {
                throw new BizException(CommonCodeEnum.ERROR);
            }
        }

        Objects.requireNonNull(cacheManager.getCache("book")).evict(bookPO.getId());

        //乐观锁只更新数量
        int result = updateBookByVersion(bookPO, request);
        if (result > 0) {
            // 等待延迟（这里使用简单的Thread.sleep作为示例，实际中应使用更合适的机制）
            try {
                Thread.sleep(DELAY_DELETE_TIME); // 延迟时间应该根据实际情况设定
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt(); // 恢复中断状态
                // 可以选择抛出异常或记录日志等
            }

            Objects.requireNonNull(cacheManager.getCache("book")).evict(bookPO.getId());
        }

        return result;
    }

    @Override
    public BookPageVO pageQueryBookList(QueryBookRequest request) {
        System.out.println("当前线程1" + Thread.currentThread().getName());
        PageInfo<BookPO> pageInfo = bookRepository.queryBookList(request.getPageNum(), request.getPageSize());
        BookPageVO bookPageVO = new BookPageVO();
        bookPageVO.setBookVOList(bookPOToVo(pageInfo.getList()));
        bookPageVO.setTotalPage(pageInfo.getPages());
        bookPageVO.setTotals(pageInfo.getTotal());
        return bookPageVO;
    }

    @Override
    @Cacheable("book")
    public BookVO queryBookById(Integer bookId) {
        BookPO bookPO = bookRepository.queryBookById(bookId);
        BookVO bookVO = new BookVO();
        BeanUtils.copyProperties(bookPO, bookVO);
        log.info("查询书本：{}", bookId);
        return bookVO;
    }

    @Override
    public List<BookVO> queryBookList(QueryBookRequest request) {
        return null;
    }

    private List<BookVO> bookPOToVo(List<BookPO> bookPOList) {
        List<BookVO> bookVOListResult = new ArrayList<>();
        if (CollectionUtils.isEmpty(bookPOList)) {
            return bookVOListResult;
        }

        for (BookPO bookPO : bookPOList) {
            BookVO bookVO = new BookVO();
            BeanUtils.copyProperties(bookPO, bookVO);
            bookVO.setCoverImage(BASE_PATH + bookVO.getCoverImage());
            bookVOListResult.add(bookVO);
        }
        return bookVOListResult;
    }

    private BookPO buildBookPO(AddBookRequest request, String fileImageUrl) {

        BookPO newBookPO = new BookPO();
        newBookPO.setCoverImage(fileImageUrl);
        newBookPO.setTitle(request.getTitle());
        //书本数量
        newBookPO.setStockQuantity(request.getStockQuantity());
        newBookPO.setAuthor(request.getAuthor());
        newBookPO.setIsbn(request.getIsbn());
        newBookPO.setCategory(request.getCategory());
        newBookPO.setDescription(request.getDescription());
        newBookPO.setPrice(request.getPrice());
        newBookPO.setCreatedTime(new Date());
        newBookPO.setUpdatedTime(new Date());
        newBookPO.setVersion(1);
        newBookPO.setCreator("田螺");
        newBookPO.setModifier("田螺");
        return newBookPO;
    }

    private Integer updateBookByVersion(BookPO bookPO, AddBookRequest request) {

        //乐观锁只更新数量
        Integer bookId = bookPO.getId();
        Integer oldVersion = bookPO.getVersion();
        Integer newStockQuantity = 0;
        if (bookPO.getStockQuantity() > 0) {
            newStockQuantity = bookPO.getStockQuantity() + request.getStockQuantity();
        } else {
            newStockQuantity = bookPO.getStockQuantity() - request.getStockQuantity();
        }

        return bookRepository.updateBookStockByIdAndVersion(bookId, oldVersion, newStockQuantity);
    }

    private String uploadBookImage(MultipartFile coverImageFile) {
        if (coverImageFile.isEmpty()) {
            throw new BizException();
        }

        try {
            // 注意：这里假设你的应用程序是以允许写入resources目录的方式运行的
            // 这通常不是生产环境的推荐做法
            String projectPath = System.getProperty("user.dir");
            System.out.println(projectPath);
            String relativePath = projectPath+"/"+"src/main/resources/static/images/";
            File staticDir = new File(relativePath);
            if (!staticDir.exists()) {
                staticDir.mkdirs(); // 如果目录不存在则创建
            }

            // 生成唯一文件名
            String originalFilename = coverImageFile.getOriginalFilename();
            String fileExtension = FilenameUtils.getExtension(originalFilename); // 使用Apache Commons IO库来获取文件扩展名
            String uniqueFilename = UUID.randomUUID().toString() + "." + fileExtension;

            // 保存文件到 static/images 目录
            File destinationFile = new File(staticDir, uniqueFilename);
            //后面第二版本优化它，用如Amazon S3、Google Cloud Storage、Azure Blob Storage等云存储服务
            coverImageFile.transferTo(destinationFile);

            // 返回访问路径（注意：在开发环境中，这通常是相对于项目根目录的路径）
            // 在生产环境中，你可能需要通过Web服务器或应用服务器的配置来映射这个路径
            return "/images/" + uniqueFilename; // 假设你的Spring Boot应用程序配置了静态资源映射到/static/下的目录
        } catch (IOException e) {
            log.warn("文件保存失败:", e);
            throw new RuntimeException("文件保存失败", e);
        }
    }
}
